﻿/*
 * LibMediaCaster.cpp
 *
 *  Created on: 2016年6月20日
 *      Author: terry
 */

#include "BasicType.h"
#include "LibMediaCaster.h"
#include "MediaCaster.h"
#include <errno.h>
#include "TMap.h"
#include "TSafeStr.h"
#include "CLog.h"
#include "MediaCasterConfig.h"



typedef comn::Map< HANDLE, av::MediaCasterPtr >     MediaCasterMap;

static MediaCasterMap s_casterMap;

av::MediaCasterPtr getCaster(HANDLE handle)
{
    av::MediaCasterPtr caster;
    s_casterMap.find(handle, caster);
    return caster;
}

av::MediaCasterPtr removeCaster(HANDLE handle)
{
    av::MediaCasterPtr caster;
    s_casterMap.remove(handle, caster);
    return caster;
}

void putCaster(HANDLE handle, av::MediaCasterPtr& caster)
{
    s_casterMap.put(handle, caster);
}

struct CMediaCasterEventSink : public av::MediaCasterEventSink
{
    CMediaCasterEventSink():
        m_cb(),
        m_context()
    {
    }

    MCasterEventCallback m_cb;
    void* m_context;

    virtual void onCasterEvent(av::MediaCasterEvent& event, int protocol)
    {
        if (m_cb)
        {
            MCasterEvent mevent;
            mevent.handle = 0;
            comn::copyStr(mevent.streamName, event.streamName);
            mevent.type = event.type;

            (*m_cb)(&mevent, protocol, m_context);
        }
    }
};

static CMediaCasterEventSink s_sink;




void copy(av::MediaFormat& mfmt, const MFormat* fmt)
{
    mfmt.m_codec = fmt->codec;
    mfmt.m_width= fmt->width;
    mfmt.m_height = fmt->height;
    mfmt.m_framerate = fmt->framerate;
    mfmt.m_profile = fmt->profile;
    mfmt.m_clockRate = fmt->clockRate;

    mfmt.m_audioCodec = fmt->audioCodec;
    mfmt.m_channels = fmt->channels;
    mfmt.m_sampleRate = fmt->sampleRate;
    mfmt.m_audioProfile = fmt->audioProfile;
    mfmt.m_audioRate = fmt->audioRate;

    if (fmt->vProp && fmt->vPropSize > 0)
    {
        mfmt.m_videoProp.assign((char*)fmt->vProp, fmt->vPropSize);
    }
}

void copyTo(const av::MediaFormat& mfmt, MFormat* fmt)
{
    fmt->codec = mfmt.m_codec;
    fmt->width = mfmt.m_width;
    fmt->height = mfmt.m_height;
    fmt->framerate = mfmt.m_framerate;
    fmt->profile = mfmt.m_profile;
    fmt->clockRate = mfmt.m_clockRate;

    fmt->audioCodec = mfmt.m_audioCodec;
    fmt->channels = mfmt.m_channels;
    fmt->sampleRate = mfmt.m_sampleRate;
    fmt->audioProfile = mfmt.m_audioProfile;
    fmt->audioRate = mfmt.m_audioRate;

    fmt->vProp = (uint8_t*)mfmt.m_videoProp.c_str();
    fmt->vPropSize = mfmt.m_videoProp.size();

}




/**
 * 初始化
 * @return
 */
DLLEXPORT int mcaster_init()
{
    CLog::setLogger(CLog::DEBUGWINDOW);

    av::getCasterManager();


    return 0;
}

/**
 *
 */
DLLEXPORT void mcaster_quit()
{
    mcaster_closeAll();

    av::getCasterManager().stopAll();

}

/**
 * 启动指定协议的媒体服务
 * @param protocol	协议 @see MCasterProtocol
 * @param ip		地址
 * @param port		端口
 * @param params	参数
 * @return 0 表示成功
 */
DLLEXPORT int mcaster_start(int protocol, const char* ip, int port, const char* params)
{
    av::getCasterManager().start(protocol, ip, port, params);

    return 0;
}

/**
 * 停止指定协议的媒体服务
 * @param protocol
 * @return
 */
DLLEXPORT int mcaster_stop(int protocol)
{
    av::getCasterManager().stop(protocol);
    return 0;
}

/**
 * 判断媒体服务是否启动
 * @param protocol
 * @return
 */
DLLEXPORT int mcaster_isStarted(int protocol)
{
    bool started = av::getCasterManager().isStarted(protocol);
    return started;
}

/**
 * 停止所有媒体服务
 */
DLLEXPORT void mcaster_stopAll()
{
    av::getCasterManager().stopAll();
}

/**
 * 创建媒体分发
 * @param handle	媒体分发句柄
 * @param name		名称
 * @param fmt		媒体格式
 * @return
 */
DLLEXPORT int mcaster_open(HANDLE* handle, const char* name, const MFormat* fmt)
{
    if (!handle)
    {
        return EINVAL;
    }

    av::MediaFormat mediaFmt;
    if (fmt)
    {
        copy(mediaFmt, fmt);
    }
    
    av::MediaCasterPtr caster = av::getCasterManager().open(name, mediaFmt);
    if (caster)
    {
        *handle = caster.get();

        putCaster(*handle, caster);
    }

    return 0;
}

/**
 * 关闭媒体分发
 * @param handle	媒体分发句柄
 * @return
 */
DLLEXPORT int mcaster_close(HANDLE handle)
{
    av::MediaCasterPtr caster = removeCaster(handle);
    if (caster)
    {
        av::getCasterManager().close(caster->getName());
    }

    return 0;
}

/**
 * 关闭所有的媒体分发
 */
DLLEXPORT void mcaster_closeAll()
{
    s_casterMap.clear();

    av::getCasterManager().closeAll();
}

/**
 * 查找媒体分发
 * @param name
 * @return
 */
DLLEXPORT HANDLE mcaster_find(const char* name)
{
    HANDLE handle = NULL;
    av::MediaCasterPtr caster =  av::getCasterManager().find(name);
    if (caster)
    {
        handle = caster.get();
    }
    return handle;
}

/**
 * 设置媒体格式
 * @param handle
 * @param fmt	媒体格式
 * @return
 */
DLLEXPORT int mcaster_setFormat(HANDLE handle, const MFormat* fmt)
{
    av::MediaCasterPtr caster = getCaster(handle);
    if (!caster)
    {
        return ENODEV;
    }

    av::MediaFormat mediaFmt;
    if (fmt)
    {
        copy(mediaFmt, fmt);
    }

    caster->setFormat(mediaFmt);

    return 0;
}

/**
 * 获取媒体格式
 * @param handle
 * @param fmt	媒体格式
 * @return
 */
DLLEXPORT int mcaster_getFormat(HANDLE handle, MFormat* fmt)
{
    av::MediaCasterPtr caster = getCaster(handle);
    if (!caster)
    {
        return ENODEV;
    }

    av::MediaFormat mediaFmt;
    if (caster->getFormat(mediaFmt))
    {
        copyTo(mediaFmt, fmt);
    }

    return 0;
}

/**
 * 写入媒体包
 * @param handle	媒体分发句柄
 * @param pkt		媒体包
 * @return
 */
DLLEXPORT int mcaster_write(HANDLE handle, const MPacket* pkt)
{
    if (!pkt)
    {
        return EINVAL;
    }

    av::MediaCasterPtr caster = getCaster(handle);
    if (!caster)
    {
        return ENODEV;
    }

    caster->write(pkt->type, pkt->data, pkt->size, pkt->pts, pkt->duration, pkt->flags);

    return 0;
}


/**
 * 设置事件回调句柄
 * @param cb		回调函数指针
 * @param context	回调环境
 */
DLLEXPORT void mcaster_setCallback(MCasterEventCallback cb, void* context)
{
    s_sink.m_cb = cb;
    s_sink.m_context = context;

    av::getCasterManager().setEventSink(&s_sink);
}

DLLEXPORT void mcaster_setQueueDuration(int ms)
{
	av::MediaCasterConfig::s_queueDuration = ms * 1000;
}

DLLEXPORT void mcaster_setSendBufSize(int size)
{
	av::MediaCasterConfig::s_sendBufSize = size;
}

